#!/usr/bin/perl
#si pas le même redpertoire mettre -I a l'appelle de perl suivi du repertoire avec les packages
use strict;
use warnings;
use p_files_with_eval_manager;
use p_index_manager;
use constant NB_CLASSE => 4;


sub where_is_the_max{
	if(!exists($_[0][0])){
		return -1;
	}
	my $cpt=0;
	my $max=0;
	while(exists($_[0][$cpt])){
		#print"$_[0][$cpt],\t";
		if($_[0][$cpt]>$_[0][$max]){
			$max=$cpt;
		}
		$cpt++;
	}
	#print"max:$max\n";
	return $max;
}

my $renewIndex = 0;
my $renewEval = 0;
if(exists($ARGV[4])){
	my $cpt=2;
	while(exists($ARGV[$cpt])){
		if($ARGV[$cpt] eq "--renewIndex"){
			$renewIndex=1;
		}elsif($ARGV[$cpt] eq "--renewEval"){
			$renewEval=1;
		}
		$cpt++;
	}
}

if(!exists($ARGV[0])){
	die("Mauvaise utilisation de 2.1-version-simple.perl, vous devez spécifier le corpus de travail\n");
}
my $nbPartition;
if(!exists($ARGV[1])){
	print "Nombre de partition mis par défaut à\t10\n";
	$nbPartition=10;
}elsif($ARGV[1]!~/^[0-9]+$/){
	print "Nombre de partition \"$ARGV[1]\" incorrect, quatité mise par défaut à\t10\n";
	$nbPartition=10;
}else{
	print "Nombre de partition mise à\t$ARGV[1]\n";
	$nbPartition=$ARGV[1];
}
my $nbIteration;
if(!exists($ARGV[2])){
	print "Nombre d'iteration mis par défaut à\t2\n";
	$nbIteration=5;
}elsif($ARGV[2]!~/^[0-9]+$/){
	print "Nombre d'iteration \"$ARGV[2]\" incorrect, quatité mise par défaut à\t2\n";
	$nbIteration=5;
}else{
	print "Nombre d'iteration mise à\t$ARGV[2]\n";
	$nbIteration=$ARGV[2];
}
my $nbInjection;
if(!exists($ARGV[3])){
	print "Nombre d'injection mis par défaut à\t1\n";
	$nbInjection=1;
}elsif($ARGV[3]!~/^[0-9]+$/){
	print "Nombre d'injection \"$ARGV[3]\" incorrect, quatité mise par défaut à\t1\n";
	$nbInjection=1;
}else{
	print "Nombre d'injection mise à\t$ARGV[3]\n";
	$nbInjection=$ARGV[3];
}

print "chargement de l'index\n";
my %index = %{&p_index_manager::get_index($ARGV[0],$renewIndex)};

print "chargement des evals\n";
my %filesWithEval = %{&p_files_with_eval_manager::getFilesWithEval($ARGV[0],$nbPartition,$renewEval)};
#le format de %filesWithEval est un hash de tableau où une ligne :  note{-1..3} determinée?{0..1} nbPartition{0..($nbPartition-1)}




#Première compléxification : les injections
for (my $injection=$nbInjection;$injection>0;$injection--){
	if($nbInjection==1){
		print "Injection unique\n";
	}else{
		print "Injections restantes après celle-ci : ".($injection)."\n";
	}
	my %proba=();
	my @qteByClasse=();
	for my $k (0..NB_CLASSE-1){
		$qteByClasse[$k]=0;
	}
	for my $klemme( keys(%index)){
		my %hDoc = %{$index{$klemme}};
		$proba{$klemme}=[1];
		for my $k (0..NB_CLASSE-1){
			$proba{$klemme}[$k]=1.1;
		}
		for my $kdoc (keys(%hDoc)){
			#si le document a une note
			if($filesWithEval{$kdoc}[0]!=-1){
				#on addition à la classe du document pour le klemme le nombre de fois qu'il est dans le document
				$proba{$klemme}[$filesWithEval{$kdoc}[0]]+=$hDoc{$kdoc};
			}
		}
	}
	#normalisation
	for my $klemme(keys(%proba)){
		for my $k (0..NB_CLASSE-1){
			$qteByClasse[$k]+=$proba{$klemme}[$k];
		}
	}
	for my $klemme(keys(%proba)){
		for my $k (0..NB_CLASSE-1){
			$proba{$klemme}[$k]/=$qteByClasse[$k];
		}
	}
	
	#notation
	my %probaDoc=();
	for my $klemme( keys(%index)){
		my %hDoc = %{$index{$klemme}};
		for my $kdoc (keys(%hDoc)){
			#si le document fait partie du corpus unsupervised et si une valeur aléatoire € [0;$injection] = 0
			if($filesWithEval{$kdoc}[1]==0 && ($injection==1 || int(rand($injection))==0)){
        # on le (re-)note
				if(!exists($probaDoc{$kdoc})){
					for my $k (0..NB_CLASSE-1){
						$probaDoc{$kdoc}[$k]=0;#0;
					}
				}
				for my $k (0..NB_CLASSE-1){
					$probaDoc{$kdoc}[$k]+=log($proba{$klemme}[$k]);
				}
			}
		}
	}
	#on lui attribut une (nouvelle) classe
	for my $kdoc( keys(%probaDoc)){
		$filesWithEval{$kdoc}[0]=&where_is_the_max($probaDoc{$kdoc});
	}
}


#deuxième compléxification : on itèr plusieurs fois
for (my $iteration=$nbIteration-1;$iteration>=0;$iteration--){
	my $sommeSscore=0;
	my $sommeTaux=0;
	my $temps=time();
	for my $paritionPourEvalutation (0..($nbPartition-1)){
		print "Evaluation sur\t$paritionPourEvalutation\n";
		#Apprentissage
		my %proba=();
		my @qteByClasse=();
		#my $sizeVocabulaire=keys(%index);
		for my $k (0..NB_CLASSE-1){
			$qteByClasse[$k]=0;
		}
		for my $klemme( keys(%index)){
			my %hDoc = %{$index{$klemme}};
			$proba{$klemme}=[1];
			for my $k (0..NB_CLASSE-1){
				$proba{$klemme}[$k]=1.1;
			}
			for my $kdoc (keys(%hDoc)){
				#si c'est pas un document dans celui utilisé pour le test, et qu'il a une note
				if($filesWithEval{$kdoc}[2]!=$paritionPourEvalutation && $filesWithEval{$kdoc}[0]!=-1){
					#on addition à la classe du document pour le klemme le nombre de fois qu'il est dans le document
					$proba{$klemme}[$filesWithEval{$kdoc}[0]]+=$hDoc{$kdoc};
				}
			}
		}
		#normalisation
		for my $klemme(keys(%proba)){
			for my $k (0..NB_CLASSE-1){
				$qteByClasse[$k]+=$proba{$klemme}[$k];
			}
		}
		for my $klemme(keys(%proba)){
			for my $k (0..NB_CLASSE-1){
				$proba{$klemme}[$k]/=$qteByClasse[$k];
			}
		}

		#Evaluation des résultats
		my $Sscore=0;
		my $nbEssai=0;
		my $nbReussite=0;
		my %probaDoc=();
		for my $klemme( keys(%index)){
			my %hDoc = %{$index{$klemme}};
			for my $kdoc (keys(%hDoc)){
				#si c'est un document utilisé pour le test
				if($filesWithEval{$kdoc}[2]==$paritionPourEvalutation){
					if(!exists($probaDoc{$kdoc})){
						for my $k (0..NB_CLASSE-1){
							$probaDoc{$kdoc}[$k]=0;#0;
						}
					}
					for my $k (0..NB_CLASSE-1){
						$probaDoc{$kdoc}[$k]+=log($proba{$klemme}[$k]);
					}
				}
			}
		}

    #Comptabilisation des echecs/réussite
		$nbEssai=keys(%probaDoc);
		my $numOfTheMax;
		for my $kdoc( keys(%probaDoc)){
			$numOfTheMax=&where_is_the_max($probaDoc{$kdoc});
			if($numOfTheMax==$filesWithEval{$kdoc}[0]){
				$nbReussite++;
				$Sscore+=1;
			}else{
				$Sscore+=exp(-abs($filesWithEval{$kdoc}[0]-$numOfTheMax));
			}
		}

		if($nbEssai==0){
			#print "le corpus était trop petit par rapport au nombre de paritionnement, en prenant ~10% du corpus nous avons prit 0 fichier.\n";
		}else{
			$Sscore/=$nbEssai;
			print "Taux de réussite : $nbReussite/$nbEssai soit\t" . int($nbReussite/$nbEssai*100) . "% avec un Sscore de "
				. int(100*$Sscore)/100 ."\n";
			$sommeTaux+=$nbReussite/$nbEssai*100;
			$sommeSscore+=$Sscore;
		}
		
	}
	print "Taux de réussite moyen :\t" . int(1000*$sommeTaux/$nbPartition)/1000 . "%\n";
	print "Sscore moyen :\t" . int(1000*$sommeSscore/$nbPartition)/1000 . "\n";
	print "Durée :\t" . (time()-$temps) . " secondes\n";

	#si c'est la dernière itération, la suite ne nous intéresse pas
	if($iteration==0){
		next;
	}
	print "Ré-apprentissage\n";
	#on va apprendre de notre notation
	my %proba=();
	my @qteByClasse=();
	for my $k (0..NB_CLASSE-1){
		$qteByClasse[$k]=0;
	}
	#apprentissage
	for my $klemme( keys(%index)){
		my %hDoc = %{$index{$klemme}};
		$proba{$klemme}=[1];
		for my $k (0..NB_CLASSE-1){
			$proba{$klemme}[$k]=1.05;
		}
		for my $kdoc (keys(%hDoc)){
			#si c'est pas un document dans celui utilisé pour le test, et qu'il a une note
			if($filesWithEval{$kdoc}[0]!=-1){
				#on addition à la classe du document pour le klemme le nombre de fois qu'il est dans le document
				$proba{$klemme}[$filesWithEval{$kdoc}[0]]+=$hDoc{$kdoc};
			}
		}
	}
	#normalisation
	for my $klemme(keys(%proba)){
		for my $k (0..NB_CLASSE-1){
			$qteByClasse[$k]+=$proba{$klemme}[$k];
		}
	}
	for my $klemme(keys(%proba)){
		for my $k (0..NB_CLASSE-1){
			$proba{$klemme}[$k]/=$qteByClasse[$k];
		}
	}
	#notation
	my %probaDoc=();
	for my $klemme( keys(%index)){
		#print "$klemme :\t$proba{$klemme}[0]\t$proba{$klemme}[1]\t$proba{$klemme}[2]\t$proba{$klemme}[3]\n";
		my %hDoc = %{$index{$klemme}};
		for my $kdoc (keys(%hDoc)){
			#si c'est un document provenant d'unsupervised
			if($filesWithEval{$kdoc}[1]==0){
				if(!exists($probaDoc{$kdoc})){
					for my $k (0..NB_CLASSE-1){
						$probaDoc{$kdoc}[$k]=0;#0;
					}
				}
				for my $k (0..NB_CLASSE-1){
					$probaDoc{$kdoc}[$k]+=log($proba{$klemme}[$k]);
				}
			}
		}
	}
	for my $kdoc( keys(%probaDoc)){
		$filesWithEval{$kdoc}[0]=&where_is_the_max($probaDoc{$kdoc});
	}
}
